package com.bm.beautifulmouse.effect;

import com.bm.beautifulmouse.model.EffectConfig;
import javafx.animation.*;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.util.Duration;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;

public class RainbowTrailEffect implements Effect {
    private final Random random = new Random();
    private final Queue<Circle> particles = new LinkedList<>();
    private final Queue<Timeline> animations = new LinkedList<>();
    private Circle lastParticle = null;
    private static final int MAX_PARTICLES = 50;
    private static final Color[] RAINBOW_COLORS = {
        Color.RED, Color.ORANGE, Color.YELLOW, 
        Color.GREEN, Color.BLUE, Color.PURPLE
    };

    @Override
    public void generate(Pane container, double x, double y, EffectConfig config) {
        // 创建新的粒子
        Circle particle = createParticle(x, y, config);
        container.getChildren().add(particle);
        
        // 如果存在上一个粒子，创建连线
        if (lastParticle != null) {
            Line connection = createConnection(lastParticle, particle);
            container.getChildren().add(connection);
            
            // 为连线创建消失动画
            Timeline connectionTimeline = new Timeline(
                new KeyFrame(Duration.ZERO, new KeyValue(connection.opacityProperty(), 0.5)),
                new KeyFrame(Duration.seconds(0.5), new KeyValue(connection.opacityProperty(), 0))
            );
            connectionTimeline.setOnFinished(e -> container.getChildren().remove(connection));
            connectionTimeline.play();
        }
        
        // 更新最后一个粒子
        lastParticle = particle;
        particles.offer(particle);
        
        // 创建粒子动画
        Timeline timeline = createAnimation(container, particle, config);
        animations.offer(timeline);
        timeline.play();
        
        // 添加旋转效果
        addRotation(particle);
        
        // 清理旧的粒子
        cleanOldParticles(container);
    }

    private Circle createParticle(double x, double y, EffectConfig config) {
        Circle particle = new Circle(3 * config.getSize());
        particle.setCenterX(x);
        particle.setCenterY(y);
        
        Color baseColor = RAINBOW_COLORS[random.nextInt(RAINBOW_COLORS.length)];
        Color randomColor = baseColor.deriveColor(
            random.nextDouble() * 360,
            0.8 + random.nextDouble() * 0.2,
            0.8 + random.nextDouble() * 0.2,
            1.0
        );
        particle.setFill(randomColor);
        particle.setEffect(new javafx.scene.effect.Glow(0.8));
        
        return particle;
    }

    private Line createConnection(Circle start, Circle end) {
        Line connection = new Line();
        connection.startXProperty().bind(start.centerXProperty());
        connection.startYProperty().bind(start.centerYProperty());
        connection.endXProperty().bind(end.centerXProperty());
        connection.endYProperty().bind(end.centerYProperty());
        connection.setStroke(start.getFill());
        connection.setStrokeWidth(2);
        connection.setOpacity(0.5);
        return connection;
    }

    private void addRotation(Circle particle) {
        RotateTransition rotate = new RotateTransition(Duration.seconds(1), particle);
        rotate.setByAngle(360);
        rotate.setCycleCount(Timeline.INDEFINITE);
        rotate.play();
    }

    private Timeline createAnimation(Pane container, Circle particle, EffectConfig config) {
        Timeline timeline = new Timeline(
            new KeyFrame(Duration.ZERO,
                new KeyValue(particle.opacityProperty(), 1.0),
                new KeyValue(particle.radiusProperty(), 3 * config.getSize())
            ),
            new KeyFrame(Duration.seconds(0.5 / config.getSpeed()),
                new KeyValue(particle.opacityProperty(), 0.0),
                new KeyValue(particle.radiusProperty(), config.getSize())
            )
        );
        
        timeline.setOnFinished(e -> {
            container.getChildren().remove(particle);
            particles.remove(particle);
            animations.remove(timeline);
            if (lastParticle == particle) {
                lastParticle = null;
            }
        });
        
        return timeline;
    }

    private void cleanOldParticles(Pane container) {
        while (particles.size() >= MAX_PARTICLES) {
            Circle oldParticle = particles.poll();
            Timeline oldAnimation = animations.poll();
            if (oldAnimation != null) {
                oldAnimation.stop();
            }
            container.getChildren().remove(oldParticle);
            if (lastParticle == oldParticle) {
                lastParticle = null;
            }
        }
    }
}